home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dev / sun4.md / devTtyAttach.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  13KB  |  499 lines

  1. /* 
  2.  * devTtyAttach.c --
  3.  *
  4.  *    This file manages the configuration of Z8530 chips on Sun-3
  5.  *    and Sun-4 workstations, and provides glue to attach the device
  6.  *    drivers for those chips to standard Sprite devices like
  7.  *    /dev/console and /dev/serialA.
  8.  *
  9.  * Copyright 1989 Regents of the University of California
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software and its documentation for any purpose and without
  12.  * fee is hereby granted, provided that the above copyright
  13.  * notice appear in all copies.  The University of California
  14.  * makes no representations about the suitability of this
  15.  * software for any purpose.  It is provided "as is" without
  16.  * express or implied warranty.
  17.  */
  18.  
  19. #ifndef lint
  20. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/sun4.md/devTtyAttach.c,v 9.7 91/10/18 01:21:50 dlong Exp $ SPRITE (Berkeley)";
  21. #endif /* not lint */
  22.  
  23. #include "sprite.h"
  24. #include "stdio.h"
  25. #include "console.h"
  26. #include "devAddrs.h"
  27. #include "mouse.h"
  28. #include "mach.h"
  29. #include "machMon.h"
  30. #include "tty.h"
  31. #include "z8530.h"
  32. #ifndef sun2
  33. #include <sys/types.h>
  34. #include <mon/eeprom.h>
  35. #endif
  36.  
  37. /*
  38.  * Forward references to procedures declared in this file:
  39.  */
  40.  
  41. static int    NullOutputChar();
  42. static int    TtyInterrupt();
  43.  
  44. #ifdef sun4c
  45.  
  46. /*
  47.  * Virtual addresses for serial device registers, extracted
  48.  * from PROM.
  49.  */
  50.  
  51. static DevZ8530Device *zsAddr[2] = {
  52.     (DevZ8530Device *)NIL, (DevZ8530Device *)NIL
  53. };
  54. static MachDevIntr zsIntr[2] = {{12, 0}, {12, 0}};
  55.  
  56. #endif
  57.  
  58. /*
  59.  * Pre-initialized data structures for three of the four channels in
  60.  * the two Z8530 SCC chips (see devMouse.c for the fourth).
  61.  */
  62.  
  63. static DevTty ttys[3];
  64.  
  65. static DevZ8530 keyboard = {
  66.     "keyboard",                    /* name */
  67. #ifdef sun4c
  68.     (DevZ8530Device *) NIL,            /* address */
  69. #else
  70.     (DevZ8530Device *) DEV_KBD_ADDR,        /* address */
  71. #endif
  72.     &ttys[0],                    /* ttyPtr */
  73. #ifdef sun4c
  74.     0,                        /* vector */
  75. #else
  76.     DEV_UART_VECTOR,                /* vector */
  77. #endif
  78.     1200,                    /* baud */
  79.     WRITE3_RX_8BIT,                /* wr3 */
  80.     WRITE5_TX_8BIT,                /* wr5 */
  81.     DevConsoleInputProc,            /* inputProc */
  82.     (ClientData) &ttys[0],            /* inputData */
  83.     NullOutputChar,                /* outputProc */
  84.     (ClientData) &ttys[0],            /* outputData */
  85.     0,                        /* oldRr0 */
  86.     Z_CHANNEL_A | Z_INACTIVE            /* flags */
  87. };
  88.  
  89. static DevZ8530 serialA = {
  90.     "serialA",                    /* name */
  91. #ifdef sun4c
  92.     (DevZ8530Device *) NIL,            /* address */
  93. #else
  94.     (DevZ8530Device *) DEV_SERIALA_ADDR,    /* address */
  95. #endif
  96.     &ttys[1],                    /* ttyPtr */
  97. #ifdef sun4c
  98.     0,                        /* vector */
  99. #else
  100.     DEV_UART_VECTOR,                /* vector */
  101. #endif
  102.     9600,                    /* baud */
  103.     WRITE3_RX_8BIT,                /* wr3 */
  104.     WRITE5_TX_8BIT,                /* wr5 */
  105.     DevTtyInputChar,                /* inputProc */
  106.     (ClientData) &ttys[1],            /* inputData */
  107.     DevTtyOutputChar,                /* outputProc */
  108.     (ClientData) &ttys[1],            /* outputData */
  109.     0,                        /* oldRr0 */
  110.     Z_CHANNEL_A | Z_INACTIVE            /* flags */
  111. };
  112.  
  113. static DevZ8530 serialB = {
  114.     "serialB",                    /* name */
  115. #ifdef sun4c
  116.     (DevZ8530Device *) NIL,            /* address */
  117. #else
  118.     (DevZ8530Device *) DEV_SERIALB_ADDR,    /* address */
  119. #endif
  120.     &ttys[2],                    /* ttyPtr */
  121. #ifdef sun4c
  122.     0,                        /* vector */
  123. #else
  124.     DEV_UART_VECTOR,                /* vector */
  125. #endif
  126.     9600,                    /* baud */
  127.     WRITE3_RX_8BIT,                /* wr3 */
  128.     WRITE5_TX_8BIT,                /* wr5 */
  129.     DevTtyInputChar,                /* inputProc */
  130.     (ClientData) &ttys[2],            /* inputData */
  131.     DevTtyOutputChar,                /* outputProc */
  132.     (ClientData) &ttys[2],            /* outputData */
  133.     0,                        /* oldRr0 */
  134.     Z_CHANNEL_B | Z_INACTIVE            /* flags */
  135. };
  136.  
  137. /*
  138.  * The following variable is filled in with the unit that should
  139.  * be used whenever "/dev/console" is opened (may be a serial unit
  140.  * if the machine doesn't have a keyboard+display).
  141.  */
  142.  
  143. static int consoleUnit = 0;
  144.  
  145. #ifdef sun4c
  146. #    include <string.h>
  147.  
  148. static int
  149. GetZSAddr(node, name, clientData)
  150.     unsigned    int             node;
  151.     char                        *name;
  152.     struct      ConfigBuf       *clientData;
  153. {
  154.     int         which;
  155.     struct      config_ops      *configPtr;
  156.  
  157.     if (strcmp(name,"zs") == 0) {
  158.     configPtr = romVectorPtr->v_config_ops;
  159.     if (configPtr->devr_getproplen(node, "keyboard") != -1) {
  160.         which = 1;
  161.     } else {
  162.         which = 0;
  163.     }
  164.     configPtr->devr_getprop(node, "address", &zsAddr[which]);
  165.     configPtr->devr_getprop(node, "intr", &zsIntr[which]);
  166.     Mach_MonPrintf("PROM: address zs %d %x intr %d\n",
  167.         which, zsAddr[which], zsIntr[which].pri);
  168.     return zsAddr[0] != (DevZ8530Device *)NIL &&
  169.            zsAddr[1] != (DevZ8530Device *)NIL;
  170.     } else {
  171.     return 0;
  172.     }
  173. }
  174. #endif
  175.  
  176. /*
  177.  *----------------------------------------------------------------------
  178.  *
  179.  * DevTtyInit --
  180.  *
  181.  *    Called during bootstrapping to initialize terminal-related
  182.  *    things.
  183.  *
  184.  * Results:
  185.  *    None.
  186.  *
  187.  * Side effects:
  188.  *    Resets serial devices and performs other initialization.
  189.  *
  190.  *----------------------------------------------------------------------
  191.  */
  192.  
  193. void
  194. DevTtyInit()
  195. {
  196.     char promConsoleType;
  197.  
  198.     /*
  199.      * Figure out whether this machine has a display for a console or
  200.      * just a terminal on a serial line.
  201.      */
  202.  
  203. #ifndef sun2
  204. #ifdef sun4c
  205.     promConsoleType = *romVectorPtr->inSource;
  206. #else
  207.     promConsoleType = ((struct eeprom *) EEPROM_BASE)->ee_diag.eed_console;
  208. #endif /* sun4c */
  209.     switch (promConsoleType) {
  210. #ifdef sun4c
  211.     case INUARTA:
  212. #else
  213.     case EED_CONS_TTYA:
  214. #endif
  215.         consoleUnit = 1;
  216.         break;
  217. #ifdef sun4c
  218.     case INUARTB:
  219. #else
  220.     case EED_CONS_TTYB:
  221. #endif
  222.         consoleUnit = 2;
  223.         break;
  224. #ifdef sun4c
  225.     case INKEYB:
  226. #else
  227.     case EED_CONS_BW:
  228.     case EED_CONS_COLOR:
  229.     case EED_CONS_P4:
  230. #endif
  231.         consoleUnit = 0;
  232.         break;
  233.     default:
  234.         printf("Warning: %s 0x%x\n",
  235.             "Dev_TtyAttach couldn't identify console type",
  236.             promConsoleType);
  237.         break;
  238.     }
  239. #endif /* sun2 */
  240.  
  241.     /*
  242.      * Reset the devices.
  243.      */
  244.  
  245. #ifdef sun4c
  246.     Mach_MonTraverseDevTree(0, GetZSAddr, (void *)NIL);
  247.     keyboard.address = (DevZ8530Device *) &zsAddr[1][1];
  248.     serialA.address = (DevZ8530Device *) &zsAddr[0][1];
  249.     serialB.address = (DevZ8530Device *) &zsAddr[0][0];
  250.     keyboard.vector = zsIntr[1].pri;
  251.     serialA.vector = serialB.vector = zsIntr[0].pri;
  252. #endif
  253.     DevZ8530RawProc((Address)&keyboard, TD_RAW_SHUTDOWN, 0, (char *) NULL,
  254.         0, (char *) NULL);
  255.     DevZ8530RawProc((Address)&serialA, TD_RAW_SHUTDOWN, 0, (char *) NULL,
  256.         0, (char *) NULL);
  257.     DevZ8530RawProc((Address)&serialB, TD_RAW_SHUTDOWN, 0, (char *) NULL,
  258.         0, (char *) NULL);
  259. #ifdef sun4c
  260.     DevMouseInit((DevZ8530Device *)&zsAddr[1][0], zsIntr[1].pri);
  261. #else
  262.     DevMouseInit();
  263. #endif
  264.  
  265. #ifdef sun4
  266. #ifdef sun4c
  267.     Mach_SetHandler(zsIntr[0].pri, TtyInterrupt, (ClientData) 0);
  268.     Mach_SetHandler(zsIntr[1].pri, TtyInterrupt, (ClientData) 0);
  269. #else /* sun4c */
  270.     Mach_SetHandler(12, TtyInterrupt, (ClientData) 0);
  271. #endif /* sun4c */
  272. #else /* sun4 */
  273.     Mach_SetHandler(DEV_UART_VECTOR, TtyInterrupt, (ClientData) 0);
  274. #endif /* sun4 */
  275.     Mach_MonStopNmi();
  276. }
  277.  
  278. /*
  279.  *----------------------------------------------------------------------
  280.  *
  281.  * DevTtyAttach --
  282.  *
  283.  *    Given a unit number, return the DevTty for the unit, properly
  284.  *    initialized.  This procedure is called as part of the open
  285.  *    sequence for a terminal.
  286.  *
  287.  * Results:
  288.  *    The return value is a pointer to a DevTty for the given unit,
  289.  *    with some of its fields filled in (see devTty.h for details).
  290.  *    If the unit number is bad, then NULL is returned.
  291.  *
  292.  * Side effects:
  293.  *    Device-specific data structures get initialized.
  294.  *
  295.  *----------------------------------------------------------------------
  296.  */
  297.  
  298. DevTty *
  299. DevTtyAttach(unit)
  300.     int unit;            /* Unit number for device. */
  301. {
  302.     register DevTty *ttyPtr;
  303.  
  304.     if ((unit > 2) || (unit < 0)) {
  305.     return NULL;
  306.     }
  307.  
  308.     /*
  309.      * If the console is one of the serial units, then disallow the
  310.      * serial unit for any use other than console.  Otherwise the
  311.      * wait tokens will get confused (two different wait tokens from
  312.      * higher-level software, but only one stored in the tty structure).
  313.      */
  314.  
  315.     if ((unit != 0) && (unit == consoleUnit)) {
  316.     return NULL;
  317.     }
  318.     
  319.     if (unit == 0) {
  320.     unit = consoleUnit;
  321.     }
  322.     ttyPtr = &ttys[unit];
  323.  
  324.     /*
  325.      * If the terminal is already open then there's nothing more to
  326.      * do;  otherwise, initialize the information relating to the
  327.      * unit.
  328.      */
  329.  
  330.     if (ttyPtr->openCount > 0) {
  331.     return ttyPtr;
  332.     }
  333.     ttyPtr->rawProc = DevZ8530RawProc;
  334.     ttyPtr->activateProc = DevZ8530Activate;
  335.     ttyPtr->inputProc = (void (*)()) NIL;
  336.     ttyPtr->inputData = (ClientData) 0;
  337.     if (unit == consoleUnit) {
  338.     ttyPtr->consoleFlags = DEV_TTY_IS_CONSOLE;
  339.     } else {
  340.     ttyPtr->consoleFlags = 0;
  341.     }
  342.  
  343.     switch (unit) {
  344.  
  345.     /*
  346.      * Unit 0 is the display+keyboard, which serves as console
  347.      * if it exists.
  348.      */
  349.  
  350.     case 0:
  351.         ttyPtr->rawProc = DevConsoleRawProc;
  352.         ttyPtr->rawData = (ClientData) &keyboard;
  353.         break;
  354.  
  355.     /*
  356.      * Unit 1 is serialA.
  357.      */
  358.  
  359.     case 1:
  360.         ttyPtr->rawData = (ClientData) &serialA;
  361.         break;
  362.  
  363.     /*
  364.      * Unit 2 is serialB.
  365.      */
  366.  
  367.     case 2:
  368.         ttyPtr->rawData = (ClientData) &serialB;
  369.         break;
  370.     }
  371.     return ttyPtr;
  372. }
  373.  
  374. /*
  375.  *----------------------------------------------------------------------
  376.  *
  377.  * DevGrabKeyboard --
  378.  *
  379.  *    This procedure is a special hack to allow events from the
  380.  *    keyboard to be redirected back and forth between /dev/console
  381.  *    and /dev/event.  DevGrabKeyboard is called to redirect input
  382.  *    keystrokes away from their normal target (/dev/console) to
  383.  *    some other place.
  384.  *
  385.  * Results:
  386.  *    The return value is a pointer to the DevZ8530 structure for
  387.  *    the keyboard (in case the caller should need to use some of
  388.  *    its fields).
  389.  *
  390.  * Side effects:
  391.  *    From now on, inputProc will be used to process input characters
  392.  *    from the keyboard and outpuProc will be used to supply output
  393.  *    characters to the keyboard.
  394.  *
  395.  *----------------------------------------------------------------------
  396.  */
  397.  
  398. DevZ8530 *
  399. DevGrabKeyboard(inputProc, inputData, outputProc, outputData)
  400.     void (*inputProc)();        /* Procedure for devTty.c to call
  401.                      * to process input characters
  402.                      * at background level. */
  403.     ClientData inputData;        /* Argument to pass to inputProc. */
  404.     int (*outputProc)();        /* Interrupt-level procedure to
  405.                      * provide next output character. */
  406.     ClientData outputData;        /* Argument to pass to outputProc. */
  407. {
  408.     ttys[0].inputProc = inputProc;
  409.     ttys[0].inputData = inputData;
  410.     keyboard.outputProc = outputProc;
  411.     keyboard.outputData = outputData;
  412.     return &keyboard;
  413. }
  414.  
  415. /*
  416.  *----------------------------------------------------------------------
  417.  *
  418.  * DevReleaseKeyboard --
  419.  *
  420.  *    This procedure is also part of the special hack to allow events
  421.  *    from the keyboard to be redirected back and forth between
  422.  *    /dev/console and /dev/event.  When the event device is closed
  423.  *    for the last time, this procedure is called to redirect keyboard
  424.  *    input back to /dev/console.
  425.  *
  426.  * Results:
  427.  *    None.
  428.  *
  429.  * Side effects:
  430.  *    Keyboard input goes to /dev/console again.
  431.  *
  432.  *----------------------------------------------------------------------
  433.  */
  434.  
  435. void
  436. DevReleaseKeyboard()
  437. {
  438.     ttys[0].inputProc = (void (*)()) NIL;
  439.     ttys[0].inputData = (ClientData) 0;
  440.     keyboard.outputProc = NullOutputChar;
  441.     keyboard.outputData = (ClientData) &ttys[0];
  442. }
  443.  
  444. /*
  445.  *----------------------------------------------------------------------
  446.  *
  447.  * TtyInterrupt --
  448.  *
  449.  *    This procedure is called whenever an interrupt occurs on
  450.  *    one of the Z8530 chips.  Various models of Sun's don't
  451.  *    handle "real" interrupt vectors from the UART chips, so the
  452.  *    safest thing is to auto-vector them all through this procedure.
  453.  *
  454.  * Results:
  455.  *    None.
  456.  *
  457.  * Side effects:
  458.  *    Each chip's interrupt handler gets invoked in turn to
  459.  *    process input and output characters for that chip.
  460.  *
  461.  *----------------------------------------------------------------------
  462.  */
  463.  
  464. static int
  465. TtyInterrupt()
  466. {
  467.     DevZ8530Interrupt((ClientData)&keyboard);
  468.     DevZ8530Interrupt((ClientData)&serialA);
  469.     DevZ8530Interrupt((ClientData)&serialB);
  470.     DevMouseInterrupt();
  471.     return 0;
  472. }
  473.  
  474. /*
  475.  *----------------------------------------------------------------------
  476.  *
  477.  * NullOutputChar --
  478.  *
  479.  *    This procedure is entered as the outputProc field of
  480.  *    DevZ8530 structures when the device is not used for
  481.  *    output.
  482.  *
  483.  * Results:
  484.  *    Always returns -1, which means "no output characters available".
  485.  *
  486.  * Side effects:
  487.  *    None.
  488.  *
  489.  *----------------------------------------------------------------------
  490.  */
  491.  
  492. /* ARGSUSED */
  493. static int
  494. NullOutputChar(clientData)
  495.     ClientData clientData;        /* Not used. */
  496. {
  497.     return -1;
  498. }
  499.